IRI.php
Current file: C:\Users\Ryan\Documents\Projects\PHP\Requests\library/Requests/IRI.php
Legend: executed not executed dead code

  Coverage
  Classes Functions / Methods Lines
Total
0.00% 0 / 1
55.56% 15 / 27 CRAP
91.62% 514 / 561
Requests_IRI
0.00% 0 / 1
55.56% 15 / 27 247.20
91.62% 514 / 561
 __toString()
100.00% 1 / 1 1
100.00% 1 / 1
 __set($name, $value)
0.00% 0 / 1 22.91
38.46% 5 / 13
 __get($name)
0.00% 0 / 1 13.48
78.26% 18 / 23
 __isset($name)
0.00% 0 / 1 12
0.00% 0 / 4
 __unset($name)
0.00% 0 / 1 6
0.00% 0 / 5
 __construct($iri = null)
100.00% 1 / 1 1
100.00% 2 / 2
 absolutize($base, $relative)
100.00% 1 / 1 20
100.00% 58 / 58
 parse_iri($iri)
0.00% 0 / 1 10.36
84.62% 22 / 26
 remove_dot_segments($input)
100.00% 1 / 1 14
100.00% 34 / 34
 replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false)
100.00% 1 / 1 28
100.00% 71 / 71
 remove_iunreserved_percent_encoded($match)
100.00% 1 / 1 36
100.00% 72 / 72
 scheme_normalization()
0.00% 0 / 1 15.34
76.00% 19 / 25
 is_valid()
100.00% 1 / 1 12
100.00% 16 / 16
 set_iri($iri)
100.00% 1 / 1 8
100.00% 33 / 33
 set_scheme($scheme)
0.00% 0 / 1 3.10
77.78% 7 / 9
 set_authority($authority)
100.00% 1 / 1 9
100.00% 39 / 39
 set_userinfo($iuserinfo)
100.00% 1 / 1 2
100.00% 7 / 7
 set_host($ihost)
0.00% 0 / 1 7.02
92.31% 24 / 26
 set_port($port)
0.00% 0 / 1 3.07
80.00% 8 / 10
 set_path($ipath)
100.00% 1 / 1 4
100.00% 16 / 16
 set_query($iquery)
100.00% 1 / 1 2
100.00% 7 / 7
 set_fragment($ifragment)
100.00% 1 / 1 2
100.00% 7 / 7
 to_uri($string)
0.00% 0 / 1 3.26
69.23% 9 / 13
 get_iri()
0.00% 0 / 1 6
95.45% 21 / 22
 get_uri()
100.00% 1 / 1 1
100.00% 1 / 1
 get_iauthority()
100.00% 1 / 1 7
100.00% 17 / 17
 get_authority()
0.00% 0 / 1 6
0.00% 0 / 4


       1                 : <?php                                                                                                                                                                                                                                                                    
       2                 : /**                                                                                                                                                                                                                                                                      
       3                 :  * IRI parser/serialiser/normaliser                                                                                                                                                                                                                                      
       4                 :  *                                                                                                                                                                                                                                                                       
       5                 :  * @package Requests                                                                                                                                                                                                                                                     
       6                 :  * @subpackage Utilities                                                                                                                                                                                                                                                 
       7                 :  */                                                                                                                                                                                                                                                                      
       8                 :                                                                                                                                                                                                                                                                          
       9                 : /**                                                                                                                                                                                                                                                                      
      10                 :  * IRI parser/serialiser/normaliser                                                                                                                                                                                                                                      
      11                 :  *                                                                                                                                                                                                                                                                       
      12                 :  * Copyright (c) 2007-2010, Geoffrey Sneddon and Steve Minutillo.                                                                                                                                                                                                        
      13                 :  * All rights reserved.                                                                                                                                                                                                                                                  
      14                 :  *                                                                                                                                                                                                                                                                       
      15                 :  * Redistribution and use in source and binary forms, with or without                                                                                                                                                                                                    
      16                 :  * modification, are permitted provided that the following conditions are met:                                                                                                                                                                                           
      17                 :  *                                                                                                                                                                                                                                                                       
      18                 :  *  * Redistributions of source code must retain the above copyright notice,                                                                                                                                                                                             
      19                 :  *       this list of conditions and the following disclaimer.                                                                                                                                                                                                           
      20                 :  *                                                                                                                                                                                                                                                                       
      21                 :  *  * Redistributions in binary form must reproduce the above copyright notice,                                                                                                                                                                                          
      22                 :  *       this list of conditions and the following disclaimer in the documentation                                                                                                                                                                                       
      23                 :  *       and/or other materials provided with the distribution.                                                                                                                                                                                                          
      24                 :  *                                                                                                                                                                                                                                                                       
      25                 :  *  * Neither the name of the SimplePie Team nor the names of its contributors                                                                                                                                                                                           
      26                 :  *       may be used to endorse or promote products derived from this software                                                                                                                                                                                           
      27                 :  *       without specific prior written permission.                                                                                                                                                                                                                      
      28                 :  *                                                                                                                                                                                                                                                                       
      29                 :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"                                                                                                                                                                                           
      30                 :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE                                                                                                                                                                                             
      31                 :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE                                                                                                                                                                                            
      32                 :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE                                                                                                                                                                                           
      33                 :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR                                                                                                                                                                                                   
      34                 :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF                                                                                                                                                                                                  
      35                 :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS                                                                                                                                                                                              
      36                 :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN                                                                                                                                                                                               
      37                 :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)                                                                                                                                                                                               
      38                 :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE                                                                                                                                                                                            
      39                 :  * POSSIBILITY OF SUCH DAMAGE.                                                                                                                                                                                                                                           
      40                 :  *                                                                                                                                                                                                                                                                       
      41                 :  * @package Requests                                                                                                                                                                                                                                                     
      42                 :  * @subpackage Utilities                                                                                                                                                                                                                                                 
      43                 :  * @author Geoffrey Sneddon                                                                                                                                                                                                                                              
      44                 :  * @author Steve Minutillo                                                                                                                                                                                                                                               
      45                 :  * @copyright 2007-2009 Geoffrey Sneddon and Steve Minutillo                                                                                                                                                                                                             
      46                 :  * @license http://www.opensource.org/licenses/bsd-license.php                                                                                                                                                                                                           
      47                 :  * @link http://hg.gsnedders.com/iri/                                                                                                                                                                                                                                    
      48                 :  */                                                                                                                                                                                                                                                                      
      49                 : class Requests_IRI                                                                                                                                                                                                                                                       
      50                 : {                                                                                                                                                                                                                                                                        
      51                 :     /**                                                                                                                                                                                                                                                                  
      52                 :      * Scheme                                                                                                                                                                                                                                                            
      53                 :      *                                                                                                                                                                                                                                                                   
      54                 :      * @var string                                                                                                                                                                                                                                                       
      55                 :      */                                                                                                                                                                                                                                                                  
      56                 :     private $scheme = null;                                                                                                                                                                                                                                              
      57                 :                                                                                                                                                                                                                                                                          
      58                 :     /**                                                                                                                                                                                                                                                                  
      59                 :      * User Information                                                                                                                                                                                                                                                  
      60                 :      *                                                                                                                                                                                                                                                                   
      61                 :      * @var string                                                                                                                                                                                                                                                       
      62                 :      */                                                                                                                                                                                                                                                                  
      63                 :     private $iuserinfo = null;                                                                                                                                                                                                                                           
      64                 :                                                                                                                                                                                                                                                                          
      65                 :     /**                                                                                                                                                                                                                                                                  
      66                 :      * ihost                                                                                                                                                                                                                                                             
      67                 :      *                                                                                                                                                                                                                                                                   
      68                 :      * @var string                                                                                                                                                                                                                                                       
      69                 :      */                                                                                                                                                                                                                                                                  
      70                 :     private $ihost = null;                                                                                                                                                                                                                                               
      71                 :                                                                                                                                                                                                                                                                          
      72                 :     /**                                                                                                                                                                                                                                                                  
      73                 :      * Port                                                                                                                                                                                                                                                              
      74                 :      *                                                                                                                                                                                                                                                                   
      75                 :      * @var string                                                                                                                                                                                                                                                       
      76                 :      */                                                                                                                                                                                                                                                                  
      77                 :     private $port = null;                                                                                                                                                                                                                                                
      78                 :                                                                                                                                                                                                                                                                          
      79                 :     /**                                                                                                                                                                                                                                                                  
      80                 :      * ipath                                                                                                                                                                                                                                                             
      81                 :      *                                                                                                                                                                                                                                                                   
      82                 :      * @var string                                                                                                                                                                                                                                                       
      83                 :      */                                                                                                                                                                                                                                                                  
      84                 :     private $ipath = '';                                                                                                                                                                                                                                                 
      85                 :                                                                                                                                                                                                                                                                          
      86                 :     /**                                                                                                                                                                                                                                                                  
      87                 :      * iquery                                                                                                                                                                                                                                                            
      88                 :      *                                                                                                                                                                                                                                                                   
      89                 :      * @var string                                                                                                                                                                                                                                                       
      90                 :      */                                                                                                                                                                                                                                                                  
      91                 :     private $iquery = null;                                                                                                                                                                                                                                              
      92                 :                                                                                                                                                                                                                                                                          
      93                 :     /**                                                                                                                                                                                                                                                                  
      94                 :      * ifragment                                                                                                                                                                                                                                                         
      95                 :      *                                                                                                                                                                                                                                                                   
      96                 :      * @var string                                                                                                                                                                                                                                                       
      97                 :      */                                                                                                                                                                                                                                                                  
      98                 :     private $ifragment = null;                                                                                                                                                                                                                                           
      99                 :                                                                                                                                                                                                                                                                          
     100                 :     /**                                                                                                                                                                                                                                                                  
     101                 :      * Normalization database                                                                                                                                                                                                                                            
     102                 :      *                                                                                                                                                                                                                                                                   
     103                 :      * Each key is the scheme, each value is an array with each key as the IRI                                                                                                                                                                                           
     104                 :      * part and value as the default value for that part.                                                                                                                                                                                                                
     105                 :      */                                                                                                                                                                                                                                                                  
     106                 :     private $normalization = array(                                                                                                                                                                                                                                      
     107                 :         'acap' => array(                                                                                                                                                                                                                                                 
     108                 :             'port' => 674                                                                                                                                                                                                                                                
     109                 :         ),                                                                                                                                                                                                                                                               
     110                 :         'dict' => array(                                                                                                                                                                                                                                                 
     111                 :             'port' => 2628                                                                                                                                                                                                                                               
     112                 :         ),                                                                                                                                                                                                                                                               
     113                 :         'file' => array(                                                                                                                                                                                                                                                 
     114                 :             'ihost' => 'localhost'                                                                                                                                                                                                                                       
     115                 :         ),                                                                                                                                                                                                                                                               
     116                 :         'http' => array(                                                                                                                                                                                                                                                 
     117                 :             'port' => 80,                                                                                                                                                                                                                                                
     118                 :             'ipath' => '/'                                                                                                                                                                                                                                               
     119                 :         ),                                                                                                                                                                                                                                                               
     120                 :         'https' => array(                                                                                                                                                                                                                                                
     121                 :             'port' => 443,                                                                                                                                                                                                                                               
     122                 :             'ipath' => '/'                                                                                                                                                                                                                                               
     123                 :         ),                                                                                                                                                                                                                                                               
     124                 :     );                                                                                                                                                                                                                                                                   
     125                 :                                                                                                                                                                                                                                                                          
     126                 :     /**                                                                                                                                                                                                                                                                  
     127                 :      * Return the entire IRI when you try and read the object as a string                                                                                                                                                                                                
     128                 :      *                                                                                                                                                                                                                                                                   
     129                 :      * @return string                                                                                                                                                                                                                                                    
     130                 :      */                                                                                                                                                                                                                                                                  
     131                 :     public function __toString()                                                                                                                                                                                                                                         
     132                 :     {                                                                                                                                                                                                                                                                    
     133             173 :         return $this->get_iri();                                                                                                                                                                                                                                         
     134                 :     }                                                                                                                                                                                                                                                                    
     135                 :                                                                                                                                                                                                                                                                          
     136                 :     /**                                                                                                                                                                                                                                                                  
     137                 :      * Overload __set() to provide access via properties                                                                                                                                                                                                                 
     138                 :      *                                                                                                                                                                                                                                                                   
     139                 :      * @param string $name Property name                                                                                                                                                                                                                                 
     140                 :      * @param mixed $value Property value                                                                                                                                                                                                                                
     141                 :      */                                                                                                                                                                                                                                                                  
     142                 :     public function __set($name, $value)                                                                                                                                                                                                                                 
     143                 :     {                                                                                                                                                                                                                                                                    
     144             133 :         if (method_exists($this, 'set_' . $name))                                                                                                                                                                                                                        
     145             133 :         {                                                                                                                                                                                                                                                                
     146             133 :             call_user_func(array($this, 'set_' . $name), $value);                                                                                                                                                                                                        
     147             133 :         }                                                                                                                                                                                                                                                                
     148                 :         elseif (                                                                                                                                                                                                                                                         
     149                 :                $name === 'iauthority'                                                                                                                                                                                                                                    
     150               0 :             || $name === 'iuserinfo'                                                                                                                                                                                                                                     
     151               0 :             || $name === 'ihost'                                                                                                                                                                                                                                         
     152               0 :             || $name === 'ipath'                                                                                                                                                                                                                                         
     153               0 :             || $name === 'iquery'                                                                                                                                                                                                                                        
     154               0 :             || $name === 'ifragment'                                                                                                                                                                                                                                     
     155               0 :         )                                                                                                                                                                                                                                                                
     156                 :         {                                                                                                                                                                                                                                                                
     157               0 :             call_user_func(array($this, 'set_' . substr($name, 1)), $value);                                                                                                                                                                                             
     158               0 :         }                                                                                                                                                                                                                                                                
     159             133 :     }                                                                                                                                                                                                                                                                    
     160                 :                                                                                                                                                                                                                                                                          
     161                 :     /**                                                                                                                                                                                                                                                                  
     162                 :      * Overload __get() to provide access via properties                                                                                                                                                                                                                 
     163                 :      *                                                                                                                                                                                                                                                                   
     164                 :      * @param string $name Property name                                                                                                                                                                                                                                 
     165                 :      * @return mixed                                                                                                                                                                                                                                                     
     166                 :      */                                                                                                                                                                                                                                                                  
     167                 :     public function __get($name)                                                                                                                                                                                                                                         
     168                 :     {                                                                                                                                                                                                                                                                    
     169                 :         // isset() returns false for null, we don't want to do that                                                                                                                                                                                                      
     170                 :         // Also why we use array_key_exists below instead of isset()                                                                                                                                                                                                     
     171             308 :         $props = get_object_vars($this);                                                                                                                                                                                                                                 
     172                 :                                                                                                                                                                                                                                                                          
     173                 :         if (                                                                                                                                                                                                                                                             
     174             308 :             $name === 'iri' ||                                                                                                                                                                                                                                           
     175             133 :             $name === 'uri' ||                                                                                                                                                                                                                                           
     176             133 :             $name === 'iauthority' ||                                                                                                                                                                                                                                    
     177                 :             $name === 'authority'                                                                                                                                                                                                                                        
     178             133 :         )                                                                                                                                                                                                                                                                
     179             308 :         {                                                                                                                                                                                                                                                                
     180             307 :             $return = $this->{"get_$name"}();                                                                                                                                                                                                                            
     181             307 :         }                                                                                                                                                                                                                                                                
     182             133 :         elseif (array_key_exists($name, $props))                                                                                                                                                                                                                         
     183                 :         {                                                                                                                                                                                                                                                                
     184             133 :             $return = $this->$name;                                                                                                                                                                                                                                      
     185             133 :         }                                                                                                                                                                                                                                                                
     186                 :         // host -> ihost                                                                                                                                                                                                                                                 
     187               1 :         elseif (($prop = 'i' . $name) && array_key_exists($prop, $props))                                                                                                                                                                                                
     188                 :         {                                                                                                                                                                                                                                                                
     189               1 :             $return = $this->$prop;                                                                                                                                                                                                                                      
     190               1 :         }                                                                                                                                                                                                                                                                
     191                 :         // ischeme -> scheme                                                                                                                                                                                                                                             
     192               0 :         elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props))                                                                                                                                                                                           
     193                 :         {                                                                                                                                                                                                                                                                
     194               0 :             $return = $this->$prop;                                                                                                                                                                                                                                      
     195               0 :         }                                                                                                                                                                                                                                                                
     196                 :         else                                                                                                                                                                                                                                                             
     197                 :         {                                                                                                                                                                                                                                                                
     198               0 :             trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);                                                                                                                                                                      
     199               0 :             $return = null;                                                                                                                                                                                                                                              
     200                 :         }                                                                                                                                                                                                                                                                
     201                 :                                                                                                                                                                                                                                                                          
     202             308 :         if ($return === null && isset($this->normalization[$this->scheme][$name]))                                                                                                                                                                                       
     203             308 :         {                                                                                                                                                                                                                                                                
     204               1 :             return $this->normalization[$this->scheme][$name];                                                                                                                                                                                                           
     205                 :         }                                                                                                                                                                                                                                                                
     206                 :         else                                                                                                                                                                                                                                                             
     207                 :         {                                                                                                                                                                                                                                                                
     208             308 :             return $return;                                                                                                                                                                                                                                              
     209                 :         }                                                                                                                                                                                                                                                                
     210                 :     }                                                                                                                                                                                                                                                                    
     211                 :                                                                                                                                                                                                                                                                          
     212                 :     /**                                                                                                                                                                                                                                                                  
     213                 :      * Overload __isset() to provide access via properties                                                                                                                                                                                                               
     214                 :      *                                                                                                                                                                                                                                                                   
     215                 :      * @param string $name Property name                                                                                                                                                                                                                                 
     216                 :      * @return bool                                                                                                                                                                                                                                                      
     217                 :      */                                                                                                                                                                                                                                                                  
     218                 :     public function __isset($name)                                                                                                                                                                                                                                       
     219                 :     {                                                                                                                                                                                                                                                                    
     220               0 :         if (method_exists($this, 'get_' . $name) || isset($this->$name))                                                                                                                                                                                                 
     221               0 :         {                                                                                                                                                                                                                                                                
     222               0 :             return true;                                                                                                                                                                                                                                                 
     223                 :         }                                                                                                                                                                                                                                                                
     224                 :         else                                                                                                                                                                                                                                                             
     225                 :         {                                                                                                                                                                                                                                                                
     226               0 :             return false;                                                                                                                                                                                                                                                
     227                 :         }                                                                                                                                                                                                                                                                
     228                 :     }                                                                                                                                                                                                                                                                    
     229                 :                                                                                                                                                                                                                                                                          
     230                 :     /**                                                                                                                                                                                                                                                                  
     231                 :      * Overload __unset() to provide access via properties                                                                                                                                                                                                               
     232                 :      *                                                                                                                                                                                                                                                                   
     233                 :      * @param string $name Property name                                                                                                                                                                                                                                 
     234                 :      */                                                                                                                                                                                                                                                                  
     235                 :     public function __unset($name)                                                                                                                                                                                                                                       
     236                 :     {                                                                                                                                                                                                                                                                    
     237               0 :         if (method_exists($this, 'set_' . $name))                                                                                                                                                                                                                        
     238               0 :         {                                                                                                                                                                                                                                                                
     239               0 :             call_user_func(array($this, 'set_' . $name), '');                                                                                                                                                                                                            
     240               0 :         }                                                                                                                                                                                                                                                                
     241               0 :     }                                                                                                                                                                                                                                                                    
     242                 :                                                                                                                                                                                                                                                                          
     243                 :     /**                                                                                                                                                                                                                                                                  
     244                 :      * Create a new IRI object, from a specified string                                                                                                                                                                                                                  
     245                 :      *                                                                                                                                                                                                                                                                   
     246                 :      * @param string $iri                                                                                                                                                                                                                                                
     247                 :      */                                                                                                                                                                                                                                                                  
     248                 :     public function __construct($iri = null)                                                                                                                                                                                                                             
     249                 :     {                                                                                                                                                                                                                                                                    
     250             445 :         $this->set_iri($iri);                                                                                                                                                                                                                                            
     251             445 :     }                                                                                                                                                                                                                                                                    
     252                 :                                                                                                                                                                                                                                                                          
     253                 :     /**                                                                                                                                                                                                                                                                  
     254                 :      * Create a new IRI object by resolving a relative IRI                                                                                                                                                                                                               
     255                 :      *                                                                                                                                                                                                                                                                   
     256                 :      * Returns false if $base is not absolute, otherwise an IRI.                                                                                                                                                                                                         
     257                 :      *                                                                                                                                                                                                                                                                   
     258                 :      * @param IRI|string $base (Absolute) Base IRI                                                                                                                                                                                                                       
     259                 :      * @param IRI|string $relative Relative IRI                                                                                                                                                                                                                          
     260                 :      * @return IRI|false                                                                                                                                                                                                                                                 
     261                 :      */                                                                                                                                                                                                                                                                  
     262                 :     public static function absolutize($base, $relative)                                                                                                                                                                                                                  
     263                 :     {                                                                                                                                                                                                                                                                    
     264             164 :         if (!($relative instanceof Requests_IRI))                                                                                                                                                                                                                        
     265             164 :         {                                                                                                                                                                                                                                                                
     266             164 :             $relative = new Requests_IRI($relative);                                                                                                                                                                                                                     
     267             164 :         }                                                                                                                                                                                                                                                                
     268             164 :         if (!$relative->is_valid())                                                                                                                                                                                                                                      
     269             164 :         {                                                                                                                                                                                                                                                                
     270               1 :             return false;                                                                                                                                                                                                                                                
     271                 :         }                                                                                                                                                                                                                                                                
     272             163 :         elseif ($relative->scheme !== null)                                                                                                                                                                                                                              
     273                 :         {                                                                                                                                                                                                                                                                
     274               6 :             return clone $relative;                                                                                                                                                                                                                                      
     275                 :         }                                                                                                                                                                                                                                                                
     276                 :         else                                                                                                                                                                                                                                                             
     277                 :         {                                                                                                                                                                                                                                                                
     278             157 :             if (!($base instanceof Requests_IRI))                                                                                                                                                                                                                        
     279             157 :             {                                                                                                                                                                                                                                                            
     280              41 :                 $base = new Requests_IRI($base);                                                                                                                                                                                                                         
     281              41 :             }                                                                                                                                                                                                                                                            
     282             157 :             if ($base->scheme !== null && $base->is_valid())                                                                                                                                                                                                             
     283             157 :             {                                                                                                                                                                                                                                                            
     284             156 :                 if ($relative->get_iri() !== '')                                                                                                                                                                                                                         
     285             156 :                 {                                                                                                                                                                                                                                                        
     286             151 :                     if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null)                                                                                                                                                          
     287             151 :                     {                                                                                                                                                                                                                                                    
     288               7 :                         $target = clone $relative;                                                                                                                                                                                                                       
     289               7 :                         $target->scheme = $base->scheme;                                                                                                                                                                                                                 
     290               7 :                     }                                                                                                                                                                                                                                                    
     291                 :                     else                                                                                                                                                                                                                                                 
     292                 :                     {                                                                                                                                                                                                                                                    
     293             144 :                         $target = new Requests_IRI;                                                                                                                                                                                                                      
     294             144 :                         $target->scheme = $base->scheme;                                                                                                                                                                                                                 
     295             144 :                         $target->iuserinfo = $base->iuserinfo;                                                                                                                                                                                                           
     296             144 :                         $target->ihost = $base->ihost;                                                                                                                                                                                                                   
     297             144 :                         $target->port = $base->port;                                                                                                                                                                                                                     
     298             144 :                         if ($relative->ipath !== '')                                                                                                                                                                                                                     
     299             144 :                         {                                                                                                                                                                                                                                                
     300             134 :                             if ($relative->ipath[0] === '/')                                                                                                                                                                                                             
     301             134 :                             {                                                                                                                                                                                                                                            
     302              11 :                                 $target->ipath = $relative->ipath;                                                                                                                                                                                                       
     303              11 :                             }                                                                                                                                                                                                                                            
     304             123 :                             elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '')                                                                                                                                 
     305                 :                             {                                                                                                                                                                                                                                            
     306               4 :                                 $target->ipath = '/' . $relative->ipath;                                                                                                                                                                                                 
     307               4 :                             }                                                                                                                                                                                                                                            
     308             119 :                             elseif (($last_segment = strrpos($base->ipath, '/')) !== false)                                                                                                                                                                              
     309                 :                             {                                                                                                                                                                                                                                            
     310             117 :                                 $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;                                                                                                                                                          
     311             117 :                             }                                                                                                                                                                                                                                            
     312                 :                             else                                                                                                                                                                                                                                         
     313                 :                             {                                                                                                                                                                                                                                            
     314               2 :                                 $target->ipath = $relative->ipath;                                                                                                                                                                                                       
     315                 :                             }                                                                                                                                                                                                                                            
     316             134 :                             $target->ipath = $target->remove_dot_segments($target->ipath);                                                                                                                                                                               
     317             134 :                             $target->iquery = $relative->iquery;                                                                                                                                                                                                         
     318             134 :                         }                                                                                                                                                                                                                                                
     319                 :                         else                                                                                                                                                                                                                                             
     320                 :                         {                                                                                                                                                                                                                                                
     321              10 :                             $target->ipath = $base->ipath;                                                                                                                                                                                                               
     322              10 :                             if ($relative->iquery !== null)                                                                                                                                                                                                              
     323              10 :                             {                                                                                                                                                                                                                                            
     324               5 :                                 $target->iquery = $relative->iquery;                                                                                                                                                                                                     
     325               5 :                             }                                                                                                                                                                                                                                            
     326               5 :                             elseif ($base->iquery !== null)                                                                                                                                                                                                              
     327                 :                             {                                                                                                                                                                                                                                            
     328               3 :                                 $target->iquery = $base->iquery;                                                                                                                                                                                                         
     329               3 :                             }                                                                                                                                                                                                                                            
     330                 :                         }                                                                                                                                                                                                                                                
     331             144 :                         $target->ifragment = $relative->ifragment;                                                                                                                                                                                                       
     332                 :                     }                                                                                                                                                                                                                                                    
     333             151 :                 }                                                                                                                                                                                                                                                        
     334                 :                 else                                                                                                                                                                                                                                                     
     335                 :                 {                                                                                                                                                                                                                                                        
     336               5 :                     $target = clone $base;                                                                                                                                                                                                                               
     337               5 :                     $target->ifragment = null;                                                                                                                                                                                                                           
     338                 :                 }                                                                                                                                                                                                                                                        
     339             156 :                 $target->scheme_normalization();                                                                                                                                                                                                                         
     340             156 :                 return $target;                                                                                                                                                                                                                                          
     341                 :             }                                                                                                                                                                                                                                                            
     342                 :             else                                                                                                                                                                                                                                                         
     343                 :             {                                                                                                                                                                                                                                                            
     344               1 :                 return false;                                                                                                                                                                                                                                            
     345                 :             }                                                                                                                                                                                                                                                            
     346                 :         }                                                                                                                                                                                                                                                                
     347                 :     }                                                                                                                                                                                                                                                                    
     348                 :                                                                                                                                                                                                                                                                          
     349                 :     /**                                                                                                                                                                                                                                                                  
     350                 :      * Parse an IRI into scheme/authority/path/query/fragment segments                                                                                                                                                                                                   
     351                 :      *                                                                                                                                                                                                                                                                   
     352                 :      * @param string $iri                                                                                                                                                                                                                                                
     353                 :      * @return array                                                                                                                                                                                                                                                     
     354                 :      */                                                                                                                                                                                                                                                                  
     355                 :     private function parse_iri($iri)                                                                                                                                                                                                                                     
     356                 :     {                                                                                                                                                                                                                                                                    
     357             249 :         $iri = trim($iri, "\x20\x09\x0A\x0C\x0D");                                                                                                                                                                                                                       
     358             249 :         if (preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match))                                                                                                            
     359             249 :         {                                                                                                                                                                                                                                                                
     360             249 :             if ($match[1] === '')                                                                                                                                                                                                                                        
     361             249 :             {                                                                                                                                                                                                                                                            
     362              56 :                 $match['scheme'] = null;                                                                                                                                                                                                                                 
     363              56 :             }                                                                                                                                                                                                                                                            
     364             249 :             if (!isset($match[3]) || $match[3] === '')                                                                                                                                                                                                                   
     365             249 :             {                                                                                                                                                                                                                                                            
     366              61 :                 $match['authority'] = null;                                                                                                                                                                                                                              
     367              61 :             }                                                                                                                                                                                                                                                            
     368             249 :             if (!isset($match[5]))                                                                                                                                                                                                                                       
     369             249 :             {                                                                                                                                                                                                                                                            
     370               0 :                 $match['path'] = '';                                                                                                                                                                                                                                     
     371               0 :             }                                                                                                                                                                                                                                                            
     372             249 :             if (!isset($match[6]) || $match[6] === '')                                                                                                                                                                                                                   
     373             249 :             {                                                                                                                                                                                                                                                            
     374             220 :                 $match['query'] = null;                                                                                                                                                                                                                                  
     375             220 :             }                                                                                                                                                                                                                                                            
     376             249 :             if (!isset($match[8]) || $match[8] === '')                                                                                                                                                                                                                   
     377             249 :             {                                                                                                                                                                                                                                                            
     378             231 :                 $match['fragment'] = null;                                                                                                                                                                                                                               
     379             231 :             }                                                                                                                                                                                                                                                            
     380             249 :             return $match;                                                                                                                                                                                                                                               
     381                 :         }                                                                                                                                                                                                                                                                
     382                 :         else                                                                                                                                                                                                                                                             
     383                 :         {                                                                                                                                                                                                                                                                
     384               0 :             trigger_error('This should never happen', E_USER_ERROR);                                                                                                                                                                                                     
     385               0 :             die;                                                                                                                                                                                                                                                         
     386                 :         }                                                                                                                                                                                                                                                                
     387                 :     }                                                                                                                                                                                                                                                                    
     388                 :                                                                                                                                                                                                                                                                          
     389                 :     /**                                                                                                                                                                                                                                                                  
     390                 :      * Remove dot segments from a path                                                                                                                                                                                                                                   
     391                 :      *                                                                                                                                                                                                                                                                   
     392                 :      * @param string $input                                                                                                                                                                                                                                              
     393                 :      * @return string                                                                                                                                                                                                                                                    
     394                 :      */                                                                                                                                                                                                                                                                  
     395                 :     private function remove_dot_segments($input)                                                                                                                                                                                                                         
     396                 :     {                                                                                                                                                                                                                                                                    
     397             229 :         $output = '';                                                                                                                                                                                                                                                    
     398             229 :         while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')                                                                                                                                                    
     399                 :         {                                                                                                                                                                                                                                                                
     400                 :             // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,                                                                                                                                   
     401              64 :             if (strpos($input, '../') === 0)                                                                                                                                                                                                                             
     402              64 :             {                                                                                                                                                                                                                                                            
     403               8 :                 $input = substr($input, 3);                                                                                                                                                                                                                              
     404               8 :             }                                                                                                                                                                                                                                                            
     405              64 :             elseif (strpos($input, './') === 0)                                                                                                                                                                                                                          
     406                 :             {                                                                                                                                                                                                                                                            
     407               4 :                 $input = substr($input, 2);                                                                                                                                                                                                                              
     408               4 :             }                                                                                                                                                                                                                                                            
     409                 :             // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,                                                                                     
     410              64 :             elseif (strpos($input, '/./') === 0)                                                                                                                                                                                                                         
     411                 :             {                                                                                                                                                                                                                                                            
     412              22 :                 $input = substr($input, 2);                                                                                                                                                                                                                              
     413              22 :             }                                                                                                                                                                                                                                                            
     414              61 :             elseif ($input === '/.')                                                                                                                                                                                                                                     
     415                 :             {                                                                                                                                                                                                                                                            
     416               6 :                 $input = '/';                                                                                                                                                                                                                                            
     417               6 :             }                                                                                                                                                                                                                                                            
     418                 :             // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
     419              61 :             elseif (strpos($input, '/../') === 0)                                                                                                                                                                                                                        
     420                 :             {                                                                                                                                                                                                                                                            
     421              34 :                 $input = substr($input, 3);                                                                                                                                                                                                                              
     422              34 :                 $output = substr_replace($output, '', strrpos($output, '/'));                                                                                                                                                                                            
     423              34 :             }                                                                                                                                                                                                                                                            
     424              58 :             elseif ($input === '/..')                                                                                                                                                                                                                                    
     425                 :             {                                                                                                                                                                                                                                                            
     426               6 :                 $input = '/';                                                                                                                                                                                                                                            
     427               6 :                 $output = substr_replace($output, '', strrpos($output, '/'));                                                                                                                                                                                            
     428               6 :             }                                                                                                                                                                                                                                                            
     429                 :             // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,                                                                                                                                                   
     430              58 :             elseif ($input === '.' || $input === '..')                                                                                                                                                                                                                   
     431                 :             {                                                                                                                                                                                                                                                            
     432               3 :                 $input = '';                                                                                                                                                                                                                                             
     433               3 :             }                                                                                                                                                                                                                                                            
     434                 :             // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer            
     435              58 :             elseif (($pos = strpos($input, '/', 1)) !== false)                                                                                                                                                                                                           
     436                 :             {                                                                                                                                                                                                                                                            
     437              58 :                 $output .= substr($input, 0, $pos);                                                                                                                                                                                                                      
     438              58 :                 $input = substr_replace($input, '', 0, $pos);                                                                                                                                                                                                            
     439              58 :             }                                                                                                                                                                                                                                                            
     440                 :             else                                                                                                                                                                                                                                                         
     441                 :             {                                                                                                                                                                                                                                                            
     442               6 :                 $output .= $input;                                                                                                                                                                                                                                       
     443               6 :                 $input = '';                                                                                                                                                                                                                                             
     444                 :             }                                                                                                                                                                                                                                                            
     445              64 :         }                                                                                                                                                                                                                                                                
     446             229 :         return $output . $input;                                                                                                                                                                                                                                         
     447                 :     }                                                                                                                                                                                                                                                                    
     448                 :                                                                                                                                                                                                                                                                          
     449                 :     /**                                                                                                                                                                                                                                                                  
     450                 :      * Replace invalid character with percent encoding                                                                                                                                                                                                                   
     451                 :      *                                                                                                                                                                                                                                                                   
     452                 :      * @param string $string Input string                                                                                                                                                                                                                                
     453                 :      * @param string $extra_chars Valid characters not in iunreserved or                                                                                                                                                                                                 
     454                 :      *                            iprivate (this is ASCII-only)                                                                                                                                                                                                          
     455                 :      * @param bool $iprivate Allow iprivate                                                                                                                                                                                                                              
     456                 :      * @return string                                                                                                                                                                                                                                                    
     457                 :      */                                                                                                                                                                                                                                                                  
     458                 :     private function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false)                                                                                                                                                                         
     459                 :     {                                                                                                                                                                                                                                                                    
     460                 :         // Normalize as many pct-encoded sections as possible                                                                                                                                                                                                            
     461             291 :         $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string);                                                                                                                                         
     462                 :                                                                                                                                                                                                                                                                          
     463                 :         // Replace invalid percent characters                                                                                                                                                                                                                            
     464             291 :         $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);                                                                                                                                                                                                 
     465                 :                                                                                                                                                                                                                                                                          
     466                 :         // Add unreserved and % to $extra_chars (the latter is safe because all                                                                                                                                                                                          
     467                 :         // pct-encoded sections are now valid).                                                                                                                                                                                                                          
     468             291 :         $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';                                                                                                                                                                           
     469                 :                                                                                                                                                                                                                                                                          
     470                 :         // Now replace any bytes that aren't allowed with their pct-encoded versions                                                                                                                                                                                     
     471             291 :         $position = 0;                                                                                                                                                                                                                                                   
     472             291 :         $strlen = strlen($string);                                                                                                                                                                                                                                       
     473             291 :         while (($position += strspn($string, $extra_chars, $position)) < $strlen)                                                                                                                                                                                        
     474                 :         {                                                                                                                                                                                                                                                                
     475              30 :             $value = ord($string[$position]);                                                                                                                                                                                                                            
     476                 :                                                                                                                                                                                                                                                                          
     477                 :             // Start position                                                                                                                                                                                                                                            
     478              30 :             $start = $position;                                                                                                                                                                                                                                          
     479                 :                                                                                                                                                                                                                                                                          
     480                 :             // By default we are valid                                                                                                                                                                                                                                   
     481              30 :             $valid = true;                                                                                                                                                                                                                                               
     482                 :                                                                                                                                                                                                                                                                          
     483                 :             // No one byte sequences are valid due to the while.                                                                                                                                                                                                         
     484                 :             // Two byte sequence:                                                                                                                                                                                                                                        
     485              30 :             if (($value & 0xE0) === 0xC0)                                                                                                                                                                                                                                
     486              30 :             {                                                                                                                                                                                                                                                            
     487              11 :                 $character = ($value & 0x1F) << 6;                                                                                                                                                                                                                       
     488              11 :                 $length = 2;                                                                                                                                                                                                                                             
     489              11 :                 $remaining = 1;                                                                                                                                                                                                                                          
     490              11 :             }                                                                                                                                                                                                                                                            
     491                 :             // Three byte sequence:                                                                                                                                                                                                                                      
     492              21 :             elseif (($value & 0xF0) === 0xE0)                                                                                                                                                                                                                            
     493                 :             {                                                                                                                                                                                                                                                            
     494               6 :                 $character = ($value & 0x0F) << 12;                                                                                                                                                                                                                      
     495               6 :                 $length = 3;                                                                                                                                                                                                                                             
     496               6 :                 $remaining = 2;                                                                                                                                                                                                                                          
     497               6 :             }                                                                                                                                                                                                                                                            
     498                 :             // Four byte sequence:                                                                                                                                                                                                                                       
     499              15 :             elseif (($value & 0xF8) === 0xF0)                                                                                                                                                                                                                            
     500                 :             {                                                                                                                                                                                                                                                            
     501               6 :                 $character = ($value & 0x07) << 18;                                                                                                                                                                                                                      
     502               6 :                 $length = 4;                                                                                                                                                                                                                                             
     503               6 :                 $remaining = 3;                                                                                                                                                                                                                                          
     504               6 :             }                                                                                                                                                                                                                                                            
     505                 :             // Invalid byte:                                                                                                                                                                                                                                             
     506                 :             else                                                                                                                                                                                                                                                         
     507                 :             {                                                                                                                                                                                                                                                            
     508               9 :                 $valid = false;                                                                                                                                                                                                                                          
     509               9 :                 $length = 1;                                                                                                                                                                                                                                             
     510               9 :                 $remaining = 0;                                                                                                                                                                                                                                          
     511                 :             }                                                                                                                                                                                                                                                            
     512                 :                                                                                                                                                                                                                                                                          
     513                 :             if ($remaining)                                                                                                                                                                                                                                              
     514              30 :             {                                                                                                                                                                                                                                                            
     515              23 :                 if ($position + $length <= $strlen)                                                                                                                                                                                                                      
     516              23 :                 {                                                                                                                                                                                                                                                        
     517              22 :                     for ($position++; $remaining; $position++)                                                                                                                                                                                                           
     518                 :                     {                                                                                                                                                                                                                                                    
     519              22 :                         $value = ord($string[$position]);                                                                                                                                                                                                                
     520                 :                                                                                                                                                                                                                                                                          
     521                 :                         // Check that the byte is valid, then add it to the character:                                                                                                                                                                                   
     522              22 :                         if (($value & 0xC0) === 0x80)                                                                                                                                                                                                                    
     523              22 :                         {                                                                                                                                                                                                                                                
     524              20 :                             $character |= ($value & 0x3F) << (--$remaining * 6);                                                                                                                                                                                         
     525              20 :                         }                                                                                                                                                                                                                                                
     526                 :                         // If it is invalid, count the sequence as invalid and reprocess the current byte:                                                                                                                                                               
     527                 :                         else                                                                                                                                                                                                                                             
     528                 :                         {                                                                                                                                                                                                                                                
     529               2 :                             $valid = false;                                                                                                                                                                                                                              
     530               2 :                             $position--;                                                                                                                                                                                                                                 
     531               2 :                             break;                                                                                                                                                                                                                                       
     532                 :                         }                                                                                                                                                                                                                                                
     533              20 :                     }                                                                                                                                                                                                                                                    
     534              22 :                 }                                                                                                                                                                                                                                                        
     535                 :                 else                                                                                                                                                                                                                                                     
     536                 :                 {                                                                                                                                                                                                                                                        
     537               1 :                     $position = $strlen - 1;                                                                                                                                                                                                                             
     538               1 :                     $valid = false;                                                                                                                                                                                                                                      
     539                 :                 }                                                                                                                                                                                                                                                        
     540              23 :             }                                                                                                                                                                                                                                                            
     541                 :                                                                                                                                                                                                                                                                          
     542                 :             // Percent encode anything invalid or not in ucschar                                                                                                                                                                                                         
     543                 :             if (                                                                                                                                                                                                                                                         
     544                 :                 // Invalid sequences                                                                                                                                                                                                                                     
     545                 :                 !$valid                                                                                                                                                                                                                                                  
     546                 :                 // Non-shortest form sequences are invalid                                                                                                                                                                                                               
     547              30 :                 || $length > 1 && $character <= 0x7F                                                                                                                                                                                                                     
     548              20 :                 || $length > 2 && $character <= 0x7FF                                                                                                                                                                                                                    
     549              20 :                 || $length > 3 && $character <= 0xFFFF                                                                                                                                                                                                                   
     550                 :                 // Outside of range of ucschar codepoints                                                                                                                                                                                                                
     551                 :                 // Noncharacters                                                                                                                                                                                                                                         
     552              20 :                 || ($character & 0xFFFE) === 0xFFFE                                                                                                                                                                                                                      
     553              20 :                 || $character >= 0xFDD0 && $character <= 0xFDEF                                                                                                                                                                                                          
     554              20 :                 || (                                                                                                                                                                                                                                                     
     555                 :                     // Everything else not in ucschar                                                                                                                                                                                                                    
     556              20 :                        $character > 0xD7FF && $character < 0xF900                                                                                                                                                                                                        
     557              12 :                     || $character < 0xA0                                                                                                                                                                                                                                 
     558              14 :                     || $character > 0xEFFFD                                                                                                                                                                                                                              
     559              14 :                 )                                                                                                                                                                                                                                                        
     560              20 :                 && (                                                                                                                                                                                                                                                     
     561                 :                     // Everything not in iprivate, if it applies                                                                                                                                                                                                         
     562                 :                        !$iprivate                                                                                                                                                                                                                                        
     563              12 :                     || $character < 0xE000                                                                                                                                                                                                                               
     564               6 :                     || $character > 0x10FFFD                                                                                                                                                                                                                             
     565               6 :                 )                                                                                                                                                                                                                                                        
     566              20 :             )                                                                                                                                                                                                                                                            
     567              30 :             {                                                                                                                                                                                                                                                            
     568                 :                 // If we were a character, pretend we weren't, but rather an error.                                                                                                                                                                                      
     569                 :                 if ($valid)                                                                                                                                                                                                                                              
     570              17 :                     $position--;                                                                                                                                                                                                                                         
     571                 :                                                                                                                                                                                                                                                                          
     572              17 :                 for ($j = $start; $j <= $position; $j++)                                                                                                                                                                                                                 
     573                 :                 {                                                                                                                                                                                                                                                        
     574              17 :                     $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);                                                                                                                                                                       
     575              17 :                     $j += 2;                                                                                                                                                                                                                                             
     576              17 :                     $position += 2;                                                                                                                                                                                                                                      
     577              17 :                     $strlen += 2;                                                                                                                                                                                                                                        
     578              17 :                 }                                                                                                                                                                                                                                                        
     579              17 :             }                                                                                                                                                                                                                                                            
     580              30 :         }                                                                                                                                                                                                                                                                
     581                 :                                                                                                                                                                                                                                                                          
     582             291 :         return $string;                                                                                                                                                                                                                                                  
     583                 :     }                                                                                                                                                                                                                                                                    
     584                 :                                                                                                                                                                                                                                                                          
     585                 :     /**                                                                                                                                                                                                                                                                  
     586                 :      * Callback function for preg_replace_callback.                                                                                                                                                                                                                      
     587                 :      *                                                                                                                                                                                                                                                                   
     588                 :      * Removes sequences of percent encoded bytes that represent UTF-8                                                                                                                                                                                                   
     589                 :      * encoded characters in iunreserved                                                                                                                                                                                                                                 
     590                 :      *                                                                                                                                                                                                                                                                   
     591                 :      * @param array $match PCRE match                                                                                                                                                                                                                                    
     592                 :      * @return string Replacement                                                                                                                                                                                                                                        
     593                 :      */                                                                                                                                                                                                                                                                  
     594                 :     private function remove_iunreserved_percent_encoded($match)                                                                                                                                                                                                          
     595                 :     {                                                                                                                                                                                                                                                                    
     596                 :         // As we just have valid percent encoded sequences we can just explode                                                                                                                                                                                           
     597                 :         // and ignore the first member of the returned array (an empty string).                                                                                                                                                                                          
     598              36 :         $bytes = explode('%', $match[0]);                                                                                                                                                                                                                                
     599                 :                                                                                                                                                                                                                                                                          
     600                 :         // Initialize the new string (this is what will be returned) and that                                                                                                                                                                                            
     601                 :         // there are no bytes remaining in the current sequence (unsurprising                                                                                                                                                                                            
     602                 :         // at the first byte!).                                                                                                                                                                                                                                          
     603              36 :         $string = '';                                                                                                                                                                                                                                                    
     604              36 :         $remaining = 0;                                                                                                                                                                                                                                                  
     605                 :                                                                                                                                                                                                                                                                          
     606                 :         // Loop over each and every byte, and set $value to its value                                                                                                                                                                                                    
     607              36 :         for ($i = 1, $len = count($bytes); $i < $len; $i++)                                                                                                                                                                                                              
     608                 :         {                                                                                                                                                                                                                                                                
     609              36 :             $value = hexdec($bytes[$i]);                                                                                                                                                                                                                                 
     610                 :                                                                                                                                                                                                                                                                          
     611                 :             // If we're the first byte of sequence:                                                                                                                                                                                                                      
     612              36 :             if (!$remaining)                                                                                                                                                                                                                                             
     613              36 :             {                                                                                                                                                                                                                                                            
     614                 :                 // Start position                                                                                                                                                                                                                                        
     615              36 :                 $start = $i;                                                                                                                                                                                                                                             
     616                 :                                                                                                                                                                                                                                                                          
     617                 :                 // By default we are valid                                                                                                                                                                                                                               
     618              36 :                 $valid = true;                                                                                                                                                                                                                                           
     619                 :                                                                                                                                                                                                                                                                          
     620                 :                 // One byte sequence:                                                                                                                                                                                                                                    
     621              36 :                 if ($value <= 0x7F)                                                                                                                                                                                                                                      
     622              36 :                 {                                                                                                                                                                                                                                                        
     623              25 :                     $character = $value;                                                                                                                                                                                                                                 
     624              25 :                     $length = 1;                                                                                                                                                                                                                                         
     625              25 :                 }                                                                                                                                                                                                                                                        
     626                 :                 // Two byte sequence:                                                                                                                                                                                                                                    
     627              16 :                 elseif (($value & 0xE0) === 0xC0)                                                                                                                                                                                                                        
     628                 :                 {                                                                                                                                                                                                                                                        
     629               7 :                     $character = ($value & 0x1F) << 6;                                                                                                                                                                                                                   
     630               7 :                     $length = 2;                                                                                                                                                                                                                                         
     631               7 :                     $remaining = 1;                                                                                                                                                                                                                                      
     632               7 :                 }                                                                                                                                                                                                                                                        
     633                 :                 // Three byte sequence:                                                                                                                                                                                                                                  
     634               9 :                 elseif (($value & 0xF0) === 0xE0)                                                                                                                                                                                                                        
     635                 :                 {                                                                                                                                                                                                                                                        
     636               3 :                     $character = ($value & 0x0F) << 12;                                                                                                                                                                                                                  
     637               3 :                     $length = 3;                                                                                                                                                                                                                                         
     638               3 :                     $remaining = 2;                                                                                                                                                                                                                                      
     639               3 :                 }                                                                                                                                                                                                                                                        
     640                 :                 // Four byte sequence:                                                                                                                                                                                                                                   
     641               6 :                 elseif (($value & 0xF8) === 0xF0)                                                                                                                                                                                                                        
     642                 :                 {                                                                                                                                                                                                                                                        
     643               3 :                     $character = ($value & 0x07) << 18;                                                                                                                                                                                                                  
     644               3 :                     $length = 4;                                                                                                                                                                                                                                         
     645               3 :                     $remaining = 3;                                                                                                                                                                                                                                      
     646               3 :                 }                                                                                                                                                                                                                                                        
     647                 :                 // Invalid byte:                                                                                                                                                                                                                                         
     648                 :                 else                                                                                                                                                                                                                                                     
     649                 :                 {                                                                                                                                                                                                                                                        
     650               3 :                     $valid = false;                                                                                                                                                                                                                                      
     651               3 :                     $remaining = 0;                                                                                                                                                                                                                                      
     652                 :                 }                                                                                                                                                                                                                                                        
     653              36 :             }                                                                                                                                                                                                                                                            
     654                 :             // Continuation byte:                                                                                                                                                                                                                                        
     655                 :             else                                                                                                                                                                                                                                                         
     656                 :             {                                                                                                                                                                                                                                                            
     657                 :                 // Check that the byte is valid, then add it to the character:                                                                                                                                                                                           
     658              11 :                 if (($value & 0xC0) === 0x80)                                                                                                                                                                                                                            
     659              11 :                 {                                                                                                                                                                                                                                                        
     660              10 :                     $remaining--;                                                                                                                                                                                                                                        
     661              10 :                     $character |= ($value & 0x3F) << ($remaining * 6);                                                                                                                                                                                                   
     662              10 :                 }                                                                                                                                                                                                                                                        
     663                 :                 // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:                                                                                                                                            
     664                 :                 else                                                                                                                                                                                                                                                     
     665                 :                 {                                                                                                                                                                                                                                                        
     666               1 :                     $valid = false;                                                                                                                                                                                                                                      
     667               1 :                     $remaining = 0;                                                                                                                                                                                                                                      
     668               1 :                     $i--;                                                                                                                                                                                                                                                
     669                 :                 }                                                                                                                                                                                                                                                        
     670                 :             }                                                                                                                                                                                                                                                            
     671                 :                                                                                                                                                                                                                                                                          
     672                 :             // If we've reached the end of the current byte sequence, append it to Unicode::$data                                                                                                                                                                        
     673              36 :             if (!$remaining)                                                                                                                                                                                                                                             
     674              36 :             {                                                                                                                                                                                                                                                            
     675                 :                 // Percent encode anything invalid or not in iunreserved                                                                                                                                                                                                 
     676                 :                 if (                                                                                                                                                                                                                                                     
     677                 :                     // Invalid sequences                                                                                                                                                                                                                                 
     678                 :                     !$valid                                                                                                                                                                                                                                              
     679                 :                     // Non-shortest form sequences are invalid                                                                                                                                                                                                           
     680              34 :                     || $length > 1 && $character <= 0x7F                                                                                                                                                                                                                 
     681              32 :                     || $length > 2 && $character <= 0x7FF                                                                                                                                                                                                                
     682              32 :                     || $length > 3 && $character <= 0xFFFF                                                                                                                                                                                                               
     683                 :                     // Outside of range of iunreserved codepoints                                                                                                                                                                                                        
     684              32 :                     || $character < 0x2D                                                                                                                                                                                                                                 
     685              32 :                     || $character > 0xEFFFD                                                                                                                                                                                                                              
     686                 :                     // Noncharacters                                                                                                                                                                                                                                     
     687              18 :                     || ($character & 0xFFFE) === 0xFFFE                                                                                                                                                                                                                  
     688              15 :                     || $character >= 0xFDD0 && $character <= 0xFDEF                                                                                                                                                                                                      
     689                 :                     // Everything else not in iunreserved (this is all BMP)                                                                                                                                                                                              
     690              15 :                     || $character === 0x2F                                                                                                                                                                                                                               
     691              15 :                     || $character > 0x39 && $character < 0x41                                                                                                                                                                                                            
     692              14 :                     || $character > 0x5A && $character < 0x61                                                                                                                                                                                                            
     693              13 :                     || $character > 0x7A && $character < 0x7E                                                                                                                                                                                                            
     694              13 :                     || $character > 0x7E && $character < 0xA0                                                                                                                                                                                                            
     695              12 :                     || $character > 0xD7FF && $character < 0xF900                                                                                                                                                                                                        
     696              12 :                 )                                                                                                                                                                                                                                                        
     697              34 :                 {                                                                                                                                                                                                                                                        
     698              27 :                     for ($j = $start; $j <= $i; $j++)                                                                                                                                                                                                                    
     699                 :                     {                                                                                                                                                                                                                                                    
     700              27 :                         $string .= '%' . strtoupper($bytes[$j]);                                                                                                                                                                                                         
     701              27 :                     }                                                                                                                                                                                                                                                    
     702              27 :                 }                                                                                                                                                                                                                                                        
     703                 :                 else                                                                                                                                                                                                                                                     
     704                 :                 {                                                                                                                                                                                                                                                        
     705               9 :                     for ($j = $start; $j <= $i; $j++)                                                                                                                                                                                                                    
     706                 :                     {                                                                                                                                                                                                                                                    
     707               9 :                         $string .= chr(hexdec($bytes[$j]));                                                                                                                                                                                                              
     708               9 :                     }                                                                                                                                                                                                                                                    
     709                 :                 }                                                                                                                                                                                                                                                        
     710              34 :             }                                                                                                                                                                                                                                                            
     711              36 :         }                                                                                                                                                                                                                                                                
     712                 :                                                                                                                                                                                                                                                                          
     713                 :         // If we have any bytes left over they are invalid (i.e., we are                                                                                                                                                                                                 
     714                 :         // mid-way through a multi-byte sequence)                                                                                                                                                                                                                        
     715                 :         if ($remaining)                                                                                                                                                                                                                                                  
     716              36 :         {                                                                                                                                                                                                                                                                
     717               2 :             for ($j = $start; $j < $len; $j++)                                                                                                                                                                                                                           
     718                 :             {                                                                                                                                                                                                                                                            
     719               2 :                 $string .= '%' . strtoupper($bytes[$j]);                                                                                                                                                                                                                 
     720               2 :             }                                                                                                                                                                                                                                                            
     721               2 :         }                                                                                                                                                                                                                                                                
     722                 :                                                                                                                                                                                                                                                                          
     723              36 :         return $string;                                                                                                                                                                                                                                                  
     724                 :     }                                                                                                                                                                                                                                                                    
     725                 :                                                                                                                                                                                                                                                                          
     726                 :     private function scheme_normalization()                                                                                                                                                                                                                              
     727                 :     {                                                                                                                                                                                                                                                                    
     728             387 :         if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo'])                                                                                                                            
     729             387 :         {                                                                                                                                                                                                                                                                
     730               0 :             $this->iuserinfo = null;                                                                                                                                                                                                                                     
     731               0 :         }                                                                                                                                                                                                                                                                
     732             387 :         if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost'])                                                                                                                                        
     733             387 :         {                                                                                                                                                                                                                                                                
     734               1 :             $this->ihost = null;                                                                                                                                                                                                                                         
     735               1 :         }                                                                                                                                                                                                                                                                
     736             387 :         if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port'])                                                                                                                                           
     737             387 :         {                                                                                                                                                                                                                                                                
     738               2 :             $this->port = null;                                                                                                                                                                                                                                          
     739               2 :         }                                                                                                                                                                                                                                                                
     740             387 :         if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath'])                                                                                                                                        
     741             387 :         {                                                                                                                                                                                                                                                                
     742              12 :             $this->ipath = '';                                                                                                                                                                                                                                           
     743              12 :         }                                                                                                                                                                                                                                                                
     744             387 :         if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery'])                                                                                                                                     
     745             387 :         {                                                                                                                                                                                                                                                                
     746               0 :             $this->iquery = null;                                                                                                                                                                                                                                        
     747               0 :         }                                                                                                                                                                                                                                                                
     748             387 :         if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment'])                                                                                                                            
     749             387 :         {                                                                                                                                                                                                                                                                
     750               0 :             $this->ifragment = null;                                                                                                                                                                                                                                     
     751               0 :         }                                                                                                                                                                                                                                                                
     752             387 :     }                                                                                                                                                                                                                                                                    
     753                 :                                                                                                                                                                                                                                                                          
     754                 :     /**                                                                                                                                                                                                                                                                  
     755                 :      * Check if the object represents a valid IRI. This needs to be done on each                                                                                                                                                                                         
     756                 :      * call as some things change depending on another part of the IRI.                                                                                                                                                                                                  
     757                 :      *                                                                                                                                                                                                                                                                   
     758                 :      * @return bool                                                                                                                                                                                                                                                      
     759                 :      */                                                                                                                                                                                                                                                                  
     760                 :     public function is_valid()                                                                                                                                                                                                                                           
     761                 :     {                                                                                                                                                                                                                                                                    
     762             369 :         $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null;                                                                                                                                                                       
     763             369 :         if ($this->ipath !== '' &&                                                                                                                                                                                                                                       
     764                 :             (                                                                                                                                                                                                                                                            
     765             314 :                 $isauthority && (                                                                                                                                                                                                                                        
     766             301 :                     $this->ipath[0] !== '/' ||                                                                                                                                                                                                                           
     767             301 :                     substr($this->ipath, 0, 2) === '//'                                                                                                                                                                                                                  
     768             301 :                 ) ||                                                                                                                                                                                                                                                     
     769                 :                 (                                                                                                                                                                                                                                                        
     770             313 :                     $this->scheme === null &&                                                                                                                                                                                                                            
     771             313 :                     !$isauthority &&                                                                                                                                                                                                                                     
     772             313 :                     strpos($this->ipath, ':') !== false &&                                                                                                                                                                                                               
     773               2 :                     (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/'))                                                                                                                                                 
     774               2 :                 )                                                                                                                                                                                                                                                        
     775             313 :             )                                                                                                                                                                                                                                                            
     776             314 :         )                                                                                                                                                                                                                                                                
     777             369 :         {                                                                                                                                                                                                                                                                
     778               1 :             return false;                                                                                                                                                                                                                                                
     779                 :         }                                                                                                                                                                                                                                                                
     780                 :                                                                                                                                                                                                                                                                          
     781             368 :         return true;                                                                                                                                                                                                                                                     
     782                 :     }                                                                                                                                                                                                                                                                    
     783                 :                                                                                                                                                                                                                                                                          
     784                 :     /**                                                                                                                                                                                                                                                                  
     785                 :      * Set the entire IRI. Returns true on success, false on failure (if there                                                                                                                                                                                           
     786                 :      * are any invalid characters).                                                                                                                                                                                                                                      
     787                 :      *                                                                                                                                                                                                                                                                   
     788                 :      * @param string $iri                                                                                                                                                                                                                                                
     789                 :      * @return bool                                                                                                                                                                                                                                                      
     790                 :      */                                                                                                                                                                                                                                                                  
     791                 :     private function set_iri($iri)                                                                                                                                                                                                                                       
     792                 :     {                                                                                                                                                                                                                                                                    
     793             445 :         static $cache;                                                                                                                                                                                                                                                   
     794             445 :         if (!$cache)                                                                                                                                                                                                                                                     
     795             445 :         {                                                                                                                                                                                                                                                                
     796               1 :             $cache = array();                                                                                                                                                                                                                                            
     797               1 :         }                                                                                                                                                                                                                                                                
     798                 :                                                                                                                                                                                                                                                                          
     799             445 :         if ($iri === null)                                                                                                                                                                                                                                               
     800             445 :         {                                                                                                                                                                                                                                                                
     801             145 :             return true;                                                                                                                                                                                                                                                 
     802                 :         }                                                                                                                                                                                                                                                                
     803             444 :         elseif (isset($cache[$iri]))                                                                                                                                                                                                                                     
     804                 :         {                                                                                                                                                                                                                                                                
     805             319 :             list($this->scheme,                                                                                                                                                                                                                                          
     806             319 :                  $this->iuserinfo,                                                                                                                                                                                                                                       
     807             319 :                  $this->ihost,                                                                                                                                                                                                                                           
     808             319 :                  $this->port,                                                                                                                                                                                                                                            
     809             319 :                  $this->ipath,                                                                                                                                                                                                                                           
     810             319 :                  $this->iquery,                                                                                                                                                                                                                                          
     811             319 :                  $this->ifragment,                                                                                                                                                                                                                                       
     812             319 :                  $return) = $cache[$iri];                                                                                                                                                                                                                                
     813             319 :             return $return;                                                                                                                                                                                                                                              
     814                 :         }                                                                                                                                                                                                                                                                
     815                 :         else                                                                                                                                                                                                                                                             
     816                 :         {                                                                                                                                                                                                                                                                
     817             249 :             $parsed = $this->parse_iri((string) $iri);                                                                                                                                                                                                                   
     818                 :                                                                                                                                                                                                                                                                          
     819             249 :             $return = $this->set_scheme($parsed['scheme'])                                                                                                                                                                                                               
     820             249 :                 && $this->set_authority($parsed['authority'])                                                                                                                                                                                                            
     821             249 :                 && $this->set_path($parsed['path'])                                                                                                                                                                                                                      
     822             249 :                 && $this->set_query($parsed['query'])                                                                                                                                                                                                                    
     823             249 :                 && $this->set_fragment($parsed['fragment']);                                                                                                                                                                                                             
     824                 :                                                                                                                                                                                                                                                                          
     825             249 :             $cache[$iri] = array($this->scheme,                                                                                                                                                                                                                          
     826             249 :                                  $this->iuserinfo,                                                                                                                                                                                                                       
     827             249 :                                  $this->ihost,                                                                                                                                                                                                                           
     828             249 :                                  $this->port,                                                                                                                                                                                                                            
     829             249 :                                  $this->ipath,                                                                                                                                                                                                                           
     830             249 :                                  $this->iquery,                                                                                                                                                                                                                          
     831             249 :                                  $this->ifragment,                                                                                                                                                                                                                       
     832             249 :                                  $return);                                                                                                                                                                                                                               
     833             249 :             return $return;                                                                                                                                                                                                                                              
     834                 :         }                                                                                                                                                                                                                                                                
     835                 :     }                                                                                                                                                                                                                                                                    
     836                 :                                                                                                                                                                                                                                                                          
     837                 :     /**                                                                                                                                                                                                                                                                  
     838                 :      * Set the scheme. Returns true on success, false on failure (if there are                                                                                                                                                                                           
     839                 :      * any invalid characters).                                                                                                                                                                                                                                          
     840                 :      *                                                                                                                                                                                                                                                                   
     841                 :      * @param string $scheme                                                                                                                                                                                                                                             
     842                 :      * @return bool                                                                                                                                                                                                                                                      
     843                 :      */                                                                                                                                                                                                                                                                  
     844                 :     private function set_scheme($scheme)                                                                                                                                                                                                                                 
     845                 :     {                                                                                                                                                                                                                                                                    
     846             250 :         if ($scheme === null)                                                                                                                                                                                                                                            
     847             250 :         {                                                                                                                                                                                                                                                                
     848              56 :             $this->scheme = null;                                                                                                                                                                                                                                        
     849              56 :         }                                                                                                                                                                                                                                                                
     850             199 :         elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme))                                                                                                                                                                                                    
     851                 :         {                                                                                                                                                                                                                                                                
     852               0 :             $this->scheme = null;                                                                                                                                                                                                                                        
     853               0 :             return false;                                                                                                                                                                                                                                                
     854                 :         }                                                                                                                                                                                                                                                                
     855                 :         else                                                                                                                                                                                                                                                             
     856                 :         {                                                                                                                                                                                                                                                                
     857             199 :             $this->scheme = strtolower($scheme);                                                                                                                                                                                                                         
     858                 :         }                                                                                                                                                                                                                                                                
     859             250 :         return true;                                                                                                                                                                                                                                                     
     860                 :     }                                                                                                                                                                                                                                                                    
     861                 :                                                                                                                                                                                                                                                                          
     862                 :     /**                                                                                                                                                                                                                                                                  
     863                 :      * Set the authority. Returns true on success, false on failure (if there are                                                                                                                                                                                        
     864                 :      * any invalid characters).                                                                                                                                                                                                                                          
     865                 :      *                                                                                                                                                                                                                                                                   
     866                 :      * @param string $authority                                                                                                                                                                                                                                          
     867                 :      * @return bool                                                                                                                                                                                                                                                      
     868                 :      */                                                                                                                                                                                                                                                                  
     869                 :     private function set_authority($authority)                                                                                                                                                                                                                           
     870                 :     {                                                                                                                                                                                                                                                                    
     871             249 :         static $cache;                                                                                                                                                                                                                                                   
     872             249 :         if (!$cache)                                                                                                                                                                                                                                                     
     873             249 :             $cache = array();                                                                                                                                                                                                                                            
     874                 :                                                                                                                                                                                                                                                                          
     875             249 :         if ($authority === null)                                                                                                                                                                                                                                         
     876             249 :         {                                                                                                                                                                                                                                                                
     877              61 :             $this->iuserinfo = null;                                                                                                                                                                                                                                     
     878              61 :             $this->ihost = null;                                                                                                                                                                                                                                         
     879              61 :             $this->port = null;                                                                                                                                                                                                                                          
     880              61 :             return true;                                                                                                                                                                                                                                                 
     881                 :         }                                                                                                                                                                                                                                                                
     882             192 :         elseif (isset($cache[$authority]))                                                                                                                                                                                                                               
     883                 :         {                                                                                                                                                                                                                                                                
     884             158 :             list($this->iuserinfo,                                                                                                                                                                                                                                       
     885             158 :                  $this->ihost,                                                                                                                                                                                                                                           
     886             158 :                  $this->port,                                                                                                                                                                                                                                            
     887             158 :                  $return) = $cache[$authority];                                                                                                                                                                                                                          
     888                 :                                                                                                                                                                                                                                                                          
     889             158 :             return $return;                                                                                                                                                                                                                                              
     890                 :         }                                                                                                                                                                                                                                                                
     891                 :         else                                                                                                                                                                                                                                                             
     892                 :         {                                                                                                                                                                                                                                                                
     893              36 :             $remaining = $authority;                                                                                                                                                                                                                                     
     894              36 :             if (($iuserinfo_end = strrpos($remaining, '@')) !== false)                                                                                                                                                                                                   
     895              36 :             {                                                                                                                                                                                                                                                            
     896               2 :                 $iuserinfo = substr($remaining, 0, $iuserinfo_end);                                                                                                                                                                                                      
     897               2 :                 $remaining = substr($remaining, $iuserinfo_end + 1);                                                                                                                                                                                                     
     898               2 :             }                                                                                                                                                                                                                                                            
     899                 :             else                                                                                                                                                                                                                                                         
     900                 :             {                                                                                                                                                                                                                                                            
     901              34 :                 $iuserinfo = null;                                                                                                                                                                                                                                       
     902                 :             }                                                                                                                                                                                                                                                            
     903              36 :             if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false)                                                                                                                                                                              
     904              36 :             {                                                                                                                                                                                                                                                            
     905               6 :                 if (($port = substr($remaining, $port_start + 1)) === false)                                                                                                                                                                                             
     906               6 :                 {                                                                                                                                                                                                                                                        
     907               2 :                     $port = null;                                                                                                                                                                                                                                        
     908               2 :                 }                                                                                                                                                                                                                                                        
     909               6 :                 $remaining = substr($remaining, 0, $port_start);                                                                                                                                                                                                         
     910               6 :             }                                                                                                                                                                                                                                                            
     911                 :             else                                                                                                                                                                                                                                                         
     912                 :             {                                                                                                                                                                                                                                                            
     913              30 :                 $port = null;                                                                                                                                                                                                                                            
     914                 :             }                                                                                                                                                                                                                                                            
     915                 :                                                                                                                                                                                                                                                                          
     916              36 :             $return = $this->set_userinfo($iuserinfo) &&                                                                                                                                                                                                                 
     917              36 :                       $this->set_host($remaining) &&                                                                                                                                                                                                                     
     918              36 :                       $this->set_port($port);                                                                                                                                                                                                                            
     919                 :                                                                                                                                                                                                                                                                          
     920              36 :             $cache[$authority] = array($this->iuserinfo,                                                                                                                                                                                                                 
     921              36 :                                        $this->ihost,                                                                                                                                                                                                                     
     922              36 :                                        $this->port,                                                                                                                                                                                                                      
     923              36 :                                        $return);                                                                                                                                                                                                                         
     924                 :                                                                                                                                                                                                                                                                          
     925              36 :             return $return;                                                                                                                                                                                                                                              
     926                 :         }                                                                                                                                                                                                                                                                
     927                 :     }                                                                                                                                                                                                                                                                    
     928                 :                                                                                                                                                                                                                                                                          
     929                 :     /**                                                                                                                                                                                                                                                                  
     930                 :      * Set the iuserinfo.                                                                                                                                                                                                                                                
     931                 :      *                                                                                                                                                                                                                                                                   
     932                 :      * @param string $iuserinfo                                                                                                                                                                                                                                          
     933                 :      * @return bool                                                                                                                                                                                                                                                      
     934                 :      */                                                                                                                                                                                                                                                                  
     935                 :     private function set_userinfo($iuserinfo)                                                                                                                                                                                                                            
     936                 :     {                                                                                                                                                                                                                                                                    
     937              37 :         if ($iuserinfo === null)                                                                                                                                                                                                                                         
     938              37 :         {                                                                                                                                                                                                                                                                
     939              34 :             $this->iuserinfo = null;                                                                                                                                                                                                                                     
     940              34 :         }                                                                                                                                                                                                                                                                
     941                 :         else                                                                                                                                                                                                                                                             
     942                 :         {                                                                                                                                                                                                                                                                
     943               3 :             $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:');                                                                                                                                                                    
     944               3 :             $this->scheme_normalization();                                                                                                                                                                                                                               
     945                 :         }                                                                                                                                                                                                                                                                
     946                 :                                                                                                                                                                                                                                                                          
     947              37 :         return true;                                                                                                                                                                                                                                                     
     948                 :     }                                                                                                                                                                                                                                                                    
     949                 :                                                                                                                                                                                                                                                                          
     950                 :     /**                                                                                                                                                                                                                                                                  
     951                 :      * Set the ihost. Returns true on success, false on failure (if there are                                                                                                                                                                                            
     952                 :      * any invalid characters).                                                                                                                                                                                                                                          
     953                 :      *                                                                                                                                                                                                                                                                   
     954                 :      * @param string $ihost                                                                                                                                                                                                                                              
     955                 :      * @return bool                                                                                                                                                                                                                                                      
     956                 :      */                                                                                                                                                                                                                                                                  
     957                 :     private function set_host($ihost)                                                                                                                                                                                                                                    
     958                 :     {                                                                                                                                                                                                                                                                    
     959             166 :         if ($ihost === null)                                                                                                                                                                                                                                             
     960             166 :         {                                                                                                                                                                                                                                                                
     961               0 :             $this->ihost = null;                                                                                                                                                                                                                                         
     962               0 :             return true;                                                                                                                                                                                                                                                 
     963                 :         }                                                                                                                                                                                                                                                                
     964             166 :         elseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']')                                                                                                                                                                                              
     965                 :         {                                                                                                                                                                                                                                                                
     966              16 :             if (Requests_IPv6::check_ipv6(substr($ihost, 1, -1)))                                                                                                                                                                                                        
     967              16 :             {                                                                                                                                                                                                                                                            
     968              15 :                 $this->ihost = '[' . Requests_IPv6::compress(substr($ihost, 1, -1)) . ']';                                                                                                                                                                               
     969              15 :             }                                                                                                                                                                                                                                                            
     970                 :             else                                                                                                                                                                                                                                                         
     971                 :             {                                                                                                                                                                                                                                                            
     972               1 :                 $this->ihost = null;                                                                                                                                                                                                                                     
     973               1 :                 return false;                                                                                                                                                                                                                                            
     974                 :             }                                                                                                                                                                                                                                                            
     975              15 :         }                                                                                                                                                                                                                                                                
     976                 :         else                                                                                                                                                                                                                                                             
     977                 :         {                                                                                                                                                                                                                                                                
     978             150 :             $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;=');                                                                                                                                                                                   
     979                 :                                                                                                                                                                                                                                                                          
     980                 :             // Lowercase, but ignore pct-encoded sections (as they should                                                                                                                                                                                                
     981                 :             // remain uppercase). This must be done after the previous step                                                                                                                                                                                              
     982                 :             // as that can add unescaped characters.                                                                                                                                                                                                                     
     983             150 :             $position = 0;                                                                                                                                                                                                                                               
     984             150 :             $strlen = strlen($ihost);                                                                                                                                                                                                                                    
     985             150 :             while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen)                                                                                                                                                                   
     986                 :             {                                                                                                                                                                                                                                                            
     987               5 :                 if ($ihost[$position] === '%')                                                                                                                                                                                                                           
     988               5 :                 {                                                                                                                                                                                                                                                        
     989               2 :                     $position += 3;                                                                                                                                                                                                                                      
     990               2 :                 }                                                                                                                                                                                                                                                        
     991                 :                 else                                                                                                                                                                                                                                                     
     992                 :                 {                                                                                                                                                                                                                                                        
     993               4 :                     $ihost[$position] = strtolower($ihost[$position]);                                                                                                                                                                                                   
     994               4 :                     $position++;                                                                                                                                                                                                                                         
     995                 :                 }                                                                                                                                                                                                                                                        
     996               5 :             }                                                                                                                                                                                                                                                            
     997                 :                                                                                                                                                                                                                                                                          
     998             150 :             $this->ihost = $ihost;                                                                                                                                                                                                                                       
     999                 :         }                                                                                                                                                                                                                                                                
    1000                 :                                                                                                                                                                                                                                                                          
    1001             165 :         $this->scheme_normalization();                                                                                                                                                                                                                                   
    1002                 :                                                                                                                                                                                                                                                                          
    1003             165 :         return true;                                                                                                                                                                                                                                                     
    1004                 :     }                                                                                                                                                                                                                                                                    
    1005                 :                                                                                                                                                                                                                                                                          
    1006                 :     /**                                                                                                                                                                                                                                                                  
    1007                 :      * Set the port. Returns true on success, false on failure (if there are                                                                                                                                                                                             
    1008                 :      * any invalid characters).                                                                                                                                                                                                                                          
    1009                 :      *                                                                                                                                                                                                                                                                   
    1010                 :      * @param string $port                                                                                                                                                                                                                                               
    1011                 :      * @return bool                                                                                                                                                                                                                                                      
    1012                 :      */                                                                                                                                                                                                                                                                  
    1013                 :     private function set_port($port)                                                                                                                                                                                                                                     
    1014                 :     {                                                                                                                                                                                                                                                                    
    1015              35 :         if ($port === null)                                                                                                                                                                                                                                              
    1016              35 :         {                                                                                                                                                                                                                                                                
    1017              31 :             $this->port = null;                                                                                                                                                                                                                                          
    1018              31 :             return true;                                                                                                                                                                                                                                                 
    1019                 :         }                                                                                                                                                                                                                                                                
    1020               4 :         elseif (strspn($port, '0123456789') === strlen($port))                                                                                                                                                                                                           
    1021                 :         {                                                                                                                                                                                                                                                                
    1022               4 :             $this->port = (int) $port;                                                                                                                                                                                                                                   
    1023               4 :             $this->scheme_normalization();                                                                                                                                                                                                                               
    1024               4 :             return true;                                                                                                                                                                                                                                                 
    1025                 :         }                                                                                                                                                                                                                                                                
    1026                 :         else                                                                                                                                                                                                                                                             
    1027                 :         {                                                                                                                                                                                                                                                                
    1028               0 :             $this->port = null;                                                                                                                                                                                                                                          
    1029               0 :             return false;                                                                                                                                                                                                                                                
    1030                 :         }                                                                                                                                                                                                                                                                
    1031                 :     }                                                                                                                                                                                                                                                                    
    1032                 :                                                                                                                                                                                                                                                                          
    1033                 :     /**                                                                                                                                                                                                                                                                  
    1034                 :      * Set the ipath.                                                                                                                                                                                                                                                    
    1035                 :      *                                                                                                                                                                                                                                                                   
    1036                 :      * @param string $ipath                                                                                                                                                                                                                                              
    1037                 :      * @return bool                                                                                                                                                                                                                                                      
    1038                 :      */                                                                                                                                                                                                                                                                  
    1039                 :     private function set_path($ipath)                                                                                                                                                                                                                                    
    1040                 :     {                                                                                                                                                                                                                                                                    
    1041             249 :         static $cache;                                                                                                                                                                                                                                                   
    1042             249 :         if (!$cache)                                                                                                                                                                                                                                                     
    1043             249 :         {                                                                                                                                                                                                                                                                
    1044               1 :             $cache = array();                                                                                                                                                                                                                                            
    1045               1 :         }                                                                                                                                                                                                                                                                
    1046                 :                                                                                                                                                                                                                                                                          
    1047             249 :         $ipath = (string) $ipath;                                                                                                                                                                                                                                        
    1048                 :                                                                                                                                                                                                                                                                          
    1049             249 :         if (isset($cache[$ipath]))                                                                                                                                                                                                                                       
    1050             249 :         {                                                                                                                                                                                                                                                                
    1051              97 :             $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)];                                                                                                                                                                                               
    1052              97 :         }                                                                                                                                                                                                                                                                
    1053                 :         else                                                                                                                                                                                                                                                             
    1054                 :         {                                                                                                                                                                                                                                                                
    1055             155 :             $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');                                                                                                                                                                                
    1056             155 :             $removed = $this->remove_dot_segments($valid);                                                                                                                                                                                                               
    1057                 :                                                                                                                                                                                                                                                                          
    1058             155 :             $cache[$ipath] = array($valid, $removed);                                                                                                                                                                                                                    
    1059             155 :             $this->ipath =  ($this->scheme !== null) ? $removed : $valid;                                                                                                                                                                                                
    1060                 :         }                                                                                                                                                                                                                                                                
    1061                 :                                                                                                                                                                                                                                                                          
    1062             249 :         $this->scheme_normalization();                                                                                                                                                                                                                                   
    1063             249 :         return true;                                                                                                                                                                                                                                                     
    1064                 :     }                                                                                                                                                                                                                                                                    
    1065                 :                                                                                                                                                                                                                                                                          
    1066                 :     /**                                                                                                                                                                                                                                                                  
    1067                 :      * Set the iquery.                                                                                                                                                                                                                                                   
    1068                 :      *                                                                                                                                                                                                                                                                   
    1069                 :      * @param string $iquery                                                                                                                                                                                                                                             
    1070                 :      * @return bool                                                                                                                                                                                                                                                      
    1071                 :      */                                                                                                                                                                                                                                                                  
    1072                 :     private function set_query($iquery)                                                                                                                                                                                                                                  
    1073                 :     {                                                                                                                                                                                                                                                                    
    1074             248 :         if ($iquery === null)                                                                                                                                                                                                                                            
    1075             248 :         {                                                                                                                                                                                                                                                                
    1076             219 :             $this->iquery = null;                                                                                                                                                                                                                                        
    1077             219 :         }                                                                                                                                                                                                                                                                
    1078                 :         else                                                                                                                                                                                                                                                             
    1079                 :         {                                                                                                                                                                                                                                                                
    1080              30 :             $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true);                                                                                                                                                                 
    1081              30 :             $this->scheme_normalization();                                                                                                                                                                                                                               
    1082                 :         }                                                                                                                                                                                                                                                                
    1083             248 :         return true;                                                                                                                                                                                                                                                     
    1084                 :     }                                                                                                                                                                                                                                                                    
    1085                 :                                                                                                                                                                                                                                                                          
    1086                 :     /**                                                                                                                                                                                                                                                                  
    1087                 :      * Set the ifragment.                                                                                                                                                                                                                                                
    1088                 :      *                                                                                                                                                                                                                                                                   
    1089                 :      * @param string $ifragment                                                                                                                                                                                                                                          
    1090                 :      * @return bool                                                                                                                                                                                                                                                      
    1091                 :      */                                                                                                                                                                                                                                                                  
    1092                 :     private function set_fragment($ifragment)                                                                                                                                                                                                                            
    1093                 :     {                                                                                                                                                                                                                                                                    
    1094             249 :         if ($ifragment === null)                                                                                                                                                                                                                                         
    1095             249 :         {                                                                                                                                                                                                                                                                
    1096             230 :             $this->ifragment = null;                                                                                                                                                                                                                                     
    1097             230 :         }                                                                                                                                                                                                                                                                
    1098                 :         else                                                                                                                                                                                                                                                             
    1099                 :         {                                                                                                                                                                                                                                                                
    1100              19 :             $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?');                                                                                                                                                                 
    1101              19 :             $this->scheme_normalization();                                                                                                                                                                                                                               
    1102                 :         }                                                                                                                                                                                                                                                                
    1103             249 :         return true;                                                                                                                                                                                                                                                     
    1104                 :     }                                                                                                                                                                                                                                                                    
    1105                 :                                                                                                                                                                                                                                                                          
    1106                 :     /**                                                                                                                                                                                                                                                                  
    1107                 :      * Convert an IRI to a URI (or parts thereof)                                                                                                                                                                                                                        
    1108                 :      *                                                                                                                                                                                                                                                                   
    1109                 :      * @return string                                                                                                                                                                                                                                                    
    1110                 :      */                                                                                                                                                                                                                                                                  
    1111                 :     private function to_uri($string)                                                                                                                                                                                                                                     
    1112                 :     {                                                                                                                                                                                                                                                                    
    1113             132 :         static $non_ascii;                                                                                                                                                                                                                                               
    1114             132 :         if (!$non_ascii)                                                                                                                                                                                                                                                 
    1115             132 :         {                                                                                                                                                                                                                                                                
    1116               1 :             $non_ascii = implode('', range("\x80", "\xFF"));                                                                                                                                                                                                             
    1117               1 :         }                                                                                                                                                                                                                                                                
    1118                 :                                                                                                                                                                                                                                                                          
    1119             132 :         $position = 0;                                                                                                                                                                                                                                                   
    1120             132 :         $strlen = strlen($string);                                                                                                                                                                                                                                       
    1121             132 :         while (($position += strcspn($string, $non_ascii, $position)) < $strlen)                                                                                                                                                                                         
    1122                 :         {                                                                                                                                                                                                                                                                
    1123               0 :             $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);                                                                                                                                                                 
    1124               0 :             $position += 3;                                                                                                                                                                                                                                              
    1125               0 :             $strlen += 2;                                                                                                                                                                                                                                                
    1126               0 :         }                                                                                                                                                                                                                                                                
    1127                 :                                                                                                                                                                                                                                                                          
    1128             132 :         return $string;                                                                                                                                                                                                                                                  
    1129                 :     }                                                                                                                                                                                                                                                                    
    1130                 :                                                                                                                                                                                                                                                                          
    1131                 :     /**                                                                                                                                                                                                                                                                  
    1132                 :      * Get the complete IRI                                                                                                                                                                                                                                              
    1133                 :      *                                                                                                                                                                                                                                                                   
    1134                 :      * @return string                                                                                                                                                                                                                                                    
    1135                 :      */                                                                                                                                                                                                                                                                  
    1136                 :     private function get_iri()                                                                                                                                                                                                                                           
    1137                 :     {                                                                                                                                                                                                                                                                    
    1138             365 :         if (!$this->is_valid())                                                                                                                                                                                                                                          
    1139             365 :         {                                                                                                                                                                                                                                                                
    1140               0 :             return false;                                                                                                                                                                                                                                                
    1141                 :         }                                                                                                                                                                                                                                                                
    1142                 :                                                                                                                                                                                                                                                                          
    1143             365 :         $iri = '';                                                                                                                                                                                                                                                       
    1144             365 :         if ($this->scheme !== null)                                                                                                                                                                                                                                      
    1145             365 :         {                                                                                                                                                                                                                                                                
    1146             306 :             $iri .= $this->scheme . ':';                                                                                                                                                                                                                                 
    1147             306 :         }                                                                                                                                                                                                                                                                
    1148             365 :         if (($iauthority = $this->get_iauthority()) !== null)                                                                                                                                                                                                            
    1149             365 :         {                                                                                                                                                                                                                                                                
    1150             299 :             $iri .= '//' . $iauthority;                                                                                                                                                                                                                                  
    1151             299 :         }                                                                                                                                                                                                                                                                
    1152             365 :         $iri .= $this->ipath;                                                                                                                                                                                                                                            
    1153             365 :         if ($this->iquery !== null)                                                                                                                                                                                                                                      
    1154             365 :         {                                                                                                                                                                                                                                                                
    1155              39 :             $iri .= '?' . $this->iquery;                                                                                                                                                                                                                                 
    1156              39 :         }                                                                                                                                                                                                                                                                
    1157             365 :         if ($this->ifragment !== null)                                                                                                                                                                                                                                   
    1158             365 :         {                                                                                                                                                                                                                                                                
    1159              23 :             $iri .= '#' . $this->ifragment;                                                                                                                                                                                                                              
    1160              23 :         }                                                                                                                                                                                                                                                                
    1161                 :                                                                                                                                                                                                                                                                          
    1162             365 :         return $iri;                                                                                                                                                                                                                                                     
    1163                 :     }                                                                                                                                                                                                                                                                    
    1164                 :                                                                                                                                                                                                                                                                          
    1165                 :     /**                                                                                                                                                                                                                                                                  
    1166                 :      * Get the complete URI                                                                                                                                                                                                                                              
    1167                 :      *                                                                                                                                                                                                                                                                   
    1168                 :      * @return string                                                                                                                                                                                                                                                    
    1169                 :      */                                                                                                                                                                                                                                                                  
    1170                 :     private function get_uri()                                                                                                                                                                                                                                           
    1171                 :     {                                                                                                                                                                                                                                                                    
    1172             132 :         return $this->to_uri($this->get_iri());                                                                                                                                                                                                                          
    1173                 :     }                                                                                                                                                                                                                                                                    
    1174                 :                                                                                                                                                                                                                                                                          
    1175                 :     /**                                                                                                                                                                                                                                                                  
    1176                 :      * Get the complete iauthority                                                                                                                                                                                                                                       
    1177                 :      *                                                                                                                                                                                                                                                                   
    1178                 :      * @return string                                                                                                                                                                                                                                                    
    1179                 :      */                                                                                                                                                                                                                                                                  
    1180                 :     private function get_iauthority()                                                                                                                                                                                                                                    
    1181                 :     {                                                                                                                                                                                                                                                                    
    1182             365 :         if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null)                                                                                                                                                                                  
    1183             365 :         {                                                                                                                                                                                                                                                                
    1184             299 :             $iauthority = '';                                                                                                                                                                                                                                            
    1185             299 :             if ($this->iuserinfo !== null)                                                                                                                                                                                                                               
    1186             299 :             {                                                                                                                                                                                                                                                            
    1187               3 :                 $iauthority .= $this->iuserinfo . '@';                                                                                                                                                                                                                   
    1188               3 :             }                                                                                                                                                                                                                                                            
    1189             299 :             if ($this->ihost !== null)                                                                                                                                                                                                                                   
    1190             299 :             {                                                                                                                                                                                                                                                            
    1191             299 :                 $iauthority .= $this->ihost;                                                                                                                                                                                                                             
    1192             299 :             }                                                                                                                                                                                                                                                            
    1193             299 :             if ($this->port !== null)                                                                                                                                                                                                                                    
    1194             299 :             {                                                                                                                                                                                                                                                            
    1195               1 :                 $iauthority .= ':' . $this->port;                                                                                                                                                                                                                        
    1196               1 :             }                                                                                                                                                                                                                                                            
    1197             299 :             return $iauthority;                                                                                                                                                                                                                                          
    1198                 :         }                                                                                                                                                                                                                                                                
    1199                 :         else                                                                                                                                                                                                                                                             
    1200                 :         {                                                                                                                                                                                                                                                                
    1201             159 :             return null;                                                                                                                                                                                                                                                 
    1202                 :         }                                                                                                                                                                                                                                                                
    1203                 :     }                                                                                                                                                                                                                                                                    
    1204                 :                                                                                                                                                                                                                                                                          
    1205                 :     /**                                                                                                                                                                                                                                                                  
    1206                 :      * Get the complete authority                                                                                                                                                                                                                                        
    1207                 :      *                                                                                                                                                                                                                                                                   
    1208                 :      * @return string                                                                                                                                                                                                                                                    
    1209                 :      */                                                                                                                                                                                                                                                                  
    1210                 :     private function get_authority()                                                                                                                                                                                                                                     
    1211                 :     {                                                                                                                                                                                                                                                                    
    1212               0 :         $iauthority = $this->get_iauthority();                                                                                                                                                                                                                           
    1213               0 :         if (is_string($iauthority))                                                                                                                                                                                                                                      
    1214               0 :             return $this->to_uri($iauthority);                                                                                                                                                                                                                           
    1215                 :         else                                                                                                                                                                                                                                                             
    1216               0 :             return $iauthority;                                                                                                                                                                                                                                          
    1217                 :     }                                                                                                                                                                                                                                                                    
    1218                 : }                                                                                                                                                                                                                                                                        

Generated by PHP_CodeCoverage 1.1.1 using PHP 5.3.8 and PHPUnit 3.6.10 at Wed Feb 8 1:55:56 EST 2012.